#include "pullcuber.h"
#include "pullsdk.h"
#include "at_tok.h"
#include "protocmd.h"
CPullCuber::CPullCuber(){
}
CPullCuber::~CPullCuber(){
}
UDK_HANDLE 
CPullCuber::Connect(const char* parameters){
  return PullSDKConnect(parameters);
}
void 
CPullCuber::Disconnect(UDK_HANDLE h){
  PullSDKDisconnect(h);
}
int CPullCuber::GetLastError()
{
  return PullSDKLastError();
}
  
int CPullCuber::SetLockState(UDK_HANDLE h,int lock_no,int opentime){
  int ret = PullSDKControlDevice(h,1/*operation id*/,lock_no/**/,1,opentime,0,NULL);
  return ret;
}

static int parse_doorsense_state(UDK_U32 v,int door){
  if(!door) return v;
  if(4==door)
	return (v&0xff000000)>>24;
  if(3==door)
	return (v&0xff0000)>>16;
  if(2==door)
	return (v&0xff00)>>8;
  if(1==door)
	return (v&0xff);
    return v;
}
static int parse_single_line(char* p,int door){
   int v1,v2,unused;
   char* str;
   int ret;
   ret = at_tok_nextstr(&p, &str);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&v1);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&unused);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&unused);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&v2);   if(ret) return ERR_CMD_UNKNOWN;
    if(255!=v2) return ERR_CMD_UNKNOWN;
    return parse_doorsense_state((UDK_U32)v1,door);
}
static int parse_rtlog(char* rt,int door){
  char* p = rt;
  char *str;
  int ret;
  int v1,v2,unused;
  ret = at_tok_start_by_token(&p,(char)'\r');
  if(ret){
    //single line?
    p = rt;
    ret = at_tok_nextstr(&p, &str);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&v1);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&unused);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&unused);   if(ret) return ERR_CMD_UNKNOWN;
    ret = at_tok_nextint(&p,&v2);   if(ret) return ERR_CMD_UNKNOWN;
    if(255!=v2) return ERR_CMD_UNKNOWN;
    return parse_doorsense_state((UDK_U32)v1,door);
  }else{
    //first line?   
    char* next = p;
    p = rt;
    ret = parse_single_line(p,door);
    if(ret>=0) return ret;
    while(next!=NULL && *next != '\0'){
	ret = parse_single_line(next,door);
        if(ret>=0) return ret;
	if(at_tok_hasmore(&next))
		at_tok_start_by_token(&next,(char)'\r');
    }
  }
  return ERR_CMD_UNKNOWN;
}

int CPullCuber::GetLockState(UDK_HANDLE h,int lock_no){
  int ret = 0;
  int buflen = 128*1024;
  char* buffer = (char*)udk_malloc(buflen);
  if(buffer){
    char* p=buffer;
    int lockcount=0;
    memset(buffer,0,buflen);
    ret = PullSDKGetDeviceParam(h,buffer,buflen,"LockCount");    
    if(ret<0) {
        udk_free(buffer);
        return ERR_CMD_DATA_PARA_ERROR;
    }
    ret = at_tok_start_by_token(&p,'=');
    if(ret<0) {
        udk_free(buffer);
        return ERR_CMD_DATA_PARA_ERROR;    
    }
    at_tok_nextint(&p,&lockcount);
    if(lock_no>lockcount){
        UDK_LOGW("invalid lock_no[%d],lockcount=%d\n",lock_no,lockcount);
        udk_free(buffer);
        return ERR_CMD_DATA_PARA_ERROR;
    }    
    //try again? it's necessary because it probably that
    //only realtime log in buffer if last command is controlDevice action 
    int maxcount=100;
    do{      
      ret = PullSDKGetRTLog(h,buffer,buflen);
      if(ret<0) {
        udk_free(buffer);
        return ret;
      }
      ret = parse_rtlog(buffer,lock_no);
      if(ret>=0) break;
    }while(--maxcount>0);
    udk_free(buffer);
  }
  return ret;
}

int CPullCuber::SearchDevices(char *CommType,char *Address, char *Buffer,int* BufferLength)
{
  return PullSDKSearchDevice(CommType,Address,Buffer,BufferLength);
}
int CPullCuber::GetLockCount(UDK_HANDLE h)
{
    int ret;
    int lockcount=0;
    char buffer[128];
    int buflen = 128;
    char* p = buffer;
    memset(buffer,0,buflen);
    ret = PullSDKGetDeviceParam(h,buffer,buflen,"LockCount");    
    if(ret<0) return ret;
    ret = at_tok_start_by_token(&p,'=');
    if(ret<0) return ERR_CMD_DATA_PARA_ERROR;    
    ret = at_tok_nextint(&p,&lockcount);
    if(!ret) return lockcount;
    return ret;    
}

int CPullCuber::GetComPwd(UDK_HANDLE h, char *buffer, int *BufferLen)
{
    int ret = 0;
    char *p = NULL, *p_end = NULL;

    ret = PullSDKGetDeviceParam(h, buffer, *BufferLen, "ComPwd");
    if (ret >= 0) {
        p = strchr(buffer, '=');
        p++;
        p_end = buffer + strlen(buffer);
        memmove(buffer, p, p_end-p);
        buffer[p_end-p] = 0;
        *BufferLen = p_end-p;
        return 0;
    } else {
        return ret;
    }
}

int CPullCuber::MobileAtt(UDK_HANDLE h, int operate, char *premeters, char *Buffer,int* BufferLength)
{
	return PullSDKMobileAtt(h, operate, premeters, Buffer, BufferLength);
}


int CPullCuber::GetDeviceParam(UDK_HANDLE h, char *Buffer, int Bufferlen, char *Item)
{
	return PullSDKGetDeviceParam(h, Buffer, Bufferlen, Item);
}

int CPullCuber::SetDeviceParam(UDK_HANDLE h, char *ItemandValues)
{
	return PullSDKSetDeviceParam(h, ItemandValues);
}

int CPullCuber::SetDownloadProcessCallBack(UDK_HANDLE h, void *pCallBackFun)
{
	return PullSDKSetDownloadProcessCallBack(h, pCallBackFun);
}

int CPullCuber::ResetDeviceExt(UDK_HANDLE h, char *parameters)
{
	return PullSDKResetDeviceExt(h, parameters);
}



